/*
main.cpp - The Program of computer what it to do.
Copyright (C) 2022 Littlelu

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/
#include <iostream>
using namespace std;
int main(){
    bool reg[10]={},mem[64][10]={},less=false,greater=false,equal=false;
    int pc=0,regnum=0,memnum=0;
    mem[63][0]=1;
    cout<<"etc copyright (C) 2022 Littlelu"<<endl;
#ifdef TEST
    //You can put test assmembly code in it.
    cout<<"Warning: TEST CODES ON."<<endl;
    //xx:9876543210
#endif
    while(true){
        if(pc<0||pc>63){
            cout<<"Error: Program counter out of limit of memory."<<endl;
            return 1;
        }
        int code=mem[pc][6]+mem[pc][7]*2+mem[pc][8]*4+mem[pc][9]*8,opnum=0;
        for(int i=0;i<6;i++) opnum+=mem[pc][i]*(1<<i);
        bool lins[10]={},car=false,subtr[10]={};
        switch(code){
        case 0:
            cout<<"Computer Halt."<<endl;
            pc++;
            return 0;
        case 1:
            pc++;
            break;
        case 2:
            for(int i=0;i<10;i++) reg[i]=mem[opnum][i];
            pc++;
            break;
        case 3:
            if(opnum==63){
                cout<<"Error: Write hardward-1."<<endl;
                return 1;
            }
            for(int i=0;i<10;i++) mem[opnum][i]=reg[i];
            pc++;
            break;
        case 4:
            for(int i=0;i<10;i++){
                lins[i]=mem[opnum][i]^reg[i]^car;
                car=(mem[opnum][i]&&reg[i])||((mem[opnum][i]^reg[i])&&car);
            }
            for(int i=0;i<10;i++) reg[i]=lins[i];
            pc++;
            break;
        case 5:
            for(int i=0;i<10;i++) subtr[i]=!mem[opnum][i];
            for(int i=0;i<10;i++){
                lins[i]=mem[63][i]^subtr[i]^car;
                car=(mem[63][i]&&subtr[i])||((mem[63][i]^subtr[i])&&car);
            }
            for(int i=0;i<10;i++) subtr[i]=lins[i];
            for(int i=0;i<10;i++){
                lins[i]=subtr[i]^reg[i]^car;
                car=(subtr[i]&&reg[i])||((subtr[i]^reg[i])&&car);
            }
            for(int i=0;i<10;i++) reg[i]=lins[i];
            pc++;
            break;
        case 6:
            for(int i=0;i<10;i++) reg[i]&=mem[opnum][i];
            pc++;
            break;
        case 7:
            for(int i=0;i<10;i++) reg[i]|=mem[opnum][i];
            pc++;
            break;
        case 8:
            for(int i=0;i<10;i++) reg[i]^=mem[opnum][i];
            pc++;
            break;
        case 9:
            for(int i=0;i<10;i++) reg[i]=!mem[opnum][i];
            pc++;
            break;
        case 10:
            for(int i=0;i<10;i++) reg[i]=!mem[opnum][i];
            for(int i=0;i<10;i++){
                lins[i]=mem[63][i]^reg[i]^car;
                car=(mem[63][i]&&reg[i])||((mem[63][i]^reg[i])&&car);
            }
            for(int i=0;i<10;i++) reg[i]=lins[i];
            pc++;
            break;
        case 11:
            regnum=0,memnum=0;
            if(reg[9]){
                for(int i=8;i>=0;i--) regnum|=((!reg[i])<<i);
                regnum=-regnum;
            }else for(int i=8;i>=0;i--) regnum|=(reg[i]<<i);
            if(mem[opnum][9]){
                for(int i=8;i>=0;i--) memnum|=((!mem[opnum][i])<<i);
                memnum=-memnum;
            }else for(int i=8;i>=0;i--) memnum|=(mem[opnum][i]<<i);
            if(regnum<memnum) less=true,equal=greater=false;
            if(regnum==memnum) equal=true,less=greater=false;
            if(regnum>memnum) greater=true,less=equal=false;
            pc++;
            break;
        case 12:
            pc=opnum;
            break;
        case 13:
            if(less) pc=opnum;
            break;
        case 14:
            if(equal) pc=opnum;
            break;
        case 15:
            if(greater) pc=opnum;
            break;
        }
    }
    return 0;
}
